package com.dragon.service.impl;

import cn.hutool.core.io.FileUtil;
import com.dragon.mapper.ContestMapper;
import com.dragon.pojo.Problem.ProblemList;
import com.dragon.pojo.Record.RecordInfo;
import com.dragon.pojo.User.UserBaseInfo;
import com.dragon.pojo.contest.*;
import com.dragon.service.ContestService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.Duration;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

@Service
public class ContestServiceImpl implements ContestService {
    @Autowired
    ContestMapper contestMapper;

    @Override
    public ContestListResult GetContestList(Integer pageNumber, Integer listNumber) {
        int offset = (pageNumber - 1) * listNumber;
        List<ContestList> contestList = contestMapper.GetContestList(offset, listNumber);

        for (ContestList contest : contestList) {
            if(contest.getStartTime().isAfter(LocalDateTime.now())){
                contest.setStatus(0);
            } else if(contest.getStartTime().isBefore(LocalDateTime.now()) && contest.getEndTime().isAfter(LocalDateTime.now())) {
                contest.setStatus(1);
            } else {
                contest.setStatus(2);
            }
        }

        return new ContestListResult(contestList, contestMapper.getContestTotal());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Object getContestInfo(Integer contestId, Integer userId) {
        Integer type = contestMapper.getContestType(contestId);
        if(type == 0) {
            Contest contest = contestMapper.getContestInfo(contestId);
            SetContestStatus(contest);
            return contest;
        } else {
            Integer isInvited = contestMapper.getIsInvited(contestId, userId);
            if(isInvited > 0) {
                Contest contest = contestMapper.getContestInfo(contestId);
                SetContestStatus(contest);
                return contest;
            } else {
                return "您没有被邀请！";
            }
        }
    }

    @Override
    public List<ProblemList> getContestProblemList(Integer contestId, Integer userId) {
        return contestMapper.getContestProblemList(contestId, userId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void addContest(ContestInfo info) {
        contestMapper.addContest(info);

        contestMapper.addContestProblem(info.getProblemIdList(), info.getContestId());

        if(info.getType() == 1) {
            contestMapper.addContestUser(info.getUserIdList(), info.getContestId());
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteContest(Integer contestId) {
        contestMapper.deleteContest(contestId);

        contestMapper.deleteContestProblem(contestId);

        contestMapper.deleteContestUser(contestId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateContestUserList(ContestUserListInfo info) {
        // 删除原来的用户列表
        contestMapper.deleteContestUser(info.getContestId());
        // 新增现在的用户列表
        contestMapper.addContestUser(info.getUserIdList(),info.getContestId());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateContest(ContestInfo info) {
        contestMapper.updateContest(info);
        // 删除原来的比赛题目
        contestMapper.deleteContestProblem(info.getContestId());
        // 添加新的比赛题目
        contestMapper.addContestProblem(info.getProblemIdList(),info.getContestId());
    }

    @Override
    public ContestRecordResult getContestRecord(Integer contestId, Integer pageNumber, Integer listNumber) {
        List<ContestRecord> list = new ArrayList<>();

        // 获取用户列表
        List<String> usernameList = contestMapper.getContestRecordUsername(contestId);
        // 获取比赛开始时间
        LocalDateTime contestStartTime = contestMapper.getContestStartTime(contestId);
        // 获取比赛题目数
        Integer problemTotal = contestMapper.getContestProblemTotal(contestId);

        // 遍历开始构造信息
        for (String username : usernameList) {
            // 累计用户总用时和分数
            long totalSecond = 0;
            Integer totalScore = 0;

            List<ContestRecordScoreList> recordScoreList = new ArrayList<>();
            // 获取分数、ac时间、和在比赛中的索引
            List<ContestRecordTemp> contestSubInfo = contestMapper.getContestSubInfo(contestId, username);

            for (int i = 0; i < problemTotal; i++) {
                recordScoreList.add(new ContestRecordScoreList());
            }
            // 构建数据
            for (ContestRecordTemp temp : contestSubInfo) {
                long seconds = Duration.between(contestStartTime, temp.getAcTime()).getSeconds();
                totalSecond += seconds;
                totalScore += temp.getScore();
                recordScoreList.set(temp.getOrder(),new ContestRecordScoreList(temp.getScore(),seconds));
            }
            list.add(new ContestRecord(username,totalScore,totalSecond,recordScoreList));
        }

        return new ContestRecordResult(list,contestMapper.getContestantTotal(contestId));
    }

    @Override
    public RecordInfo getContestRecordInfo(Integer recordId, Integer userId) {
        RecordInfo recordInfo = contestMapper.getContestRecordInfo(recordId);
        if(userId != null) {
            if(recordInfo.getUserId().equals(userId)) {
                recordInfo.setSourceCode(FileUtil.readUtf8String(recordInfo.getCodePath()));
            }
        }
        return recordInfo;
    }

    @Override
    public List<UserBaseInfo> getContestUserList(Integer contestId) {
        return contestMapper.getUserBaseInfoByContestId(contestId);
    }

    private void SetContestStatus(Contest contest) {
        if(contest.getStartTime().isAfter(LocalDateTime.now())){
            contest.setStatus(0);
        } else if(contest.getStartTime().isBefore(LocalDateTime.now()) && contest.getEndTime().isAfter(LocalDateTime.now())) {
            contest.setStatus(1);
        } else {
            contest.setStatus(2);
        }
    }
}
